﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;

/// <summary>
/// Heros TreeView保存和恢复结点展开状态的辅助类
/// </summary>
public class TreeNodesExpandStateManager : IDisposable
{
    TreeView _tree;
    List<TreeNode> nodes = new List<TreeNode>();

    public static string SessionKey = "TreeNodesExpandState";
    public TreeNodesExpandStateManager(TreeView tree)
    {
        _tree = tree;
    }

    /// <summary>
    /// 保存当前树的展开状态
    /// </summary>
    public void SaveExpandState()
    {
        foreach (TreeNode node in this._tree.Nodes)
        {
            SearchExpandedNode(node);
        }
    }

    private void SearchExpandedNode(TreeNode node)
    {
        if (node == null)
            return;
        else
        {
            if (node.Expanded ?? false)
            {
                nodes.Add(node);
                foreach (TreeNode item in node.ChildNodes)
                {
                    SearchExpandedNode(item);
                }
            }
        }
    }

    /// <summary>
    /// 恢复当前树的展开状态
    /// </summary>
    public void RestoreExpandState()
    {
        foreach (TreeNode node in this._tree.Nodes)
        {
            SetNodeExpandState(node);
        }
    }

    /// <summary>
    /// 用于跨页操作时，恢复到指定树
    /// </summary>
    /// <param name="tree"></param>
    public void RestoreExpandStateToTree(TreeView tree)
    {
        foreach (TreeNode node in tree.Nodes)
        {
            SetNodeExpandState(node);
        }
    }

    private void SetNodeExpandState(TreeNode node)
    {
        if (node == null)
            return;
        else
        {
            if (this.nodes.Contains(node, new EqualEntity()))
            {
                node.Expand();
                foreach (TreeNode item in node.ChildNodes)
                {
                    SetNodeExpandState(item);
                }
            }
        }
    }

    /// <summary>
    /// 将指定树展开状态存入会话，一般在树的展开和合闭事件中调用
    /// </summary>
    /// <param name="tree">目标树</param>
    public static void SaveExpandStateInSession(TreeView tree, string sessionKey)
    {
        if (tree == null)
            return;
        TreeNodesExpandStateManager manager = new TreeNodesExpandStateManager(tree);
        manager.SaveExpandState();
        HttpContext.Current.Session[sessionKey] = manager;
    }

    /// <summary>
    /// 将指定树展开状态存入默认会话，一般在树的展开和合闭事件中调用
    /// </summary>
    /// <param name="tree">目标树</param>
    public static void SaveExpandStateInSession(TreeView tree)
    {
        SaveExpandStateInSession(tree, SessionKey);
    }

    /// <summary>
    /// 将Session中的结点展开状态恢复到指定树，在树结点添加结束后调用
    /// </summary>
    /// <param name="tree">目标树</param>
    public static void RestoreExpandStateToTreeFromSession(TreeView tree, string sessionKey)
    {
        if (HttpContext.Current.Session[sessionKey] == null || tree == null)
            return;
        TreeNodesExpandStateManager manager = HttpContext.Current.Session[sessionKey] as TreeNodesExpandStateManager;
        manager.RestoreExpandStateToTree(tree);
    }
    /// <summary>
    /// 将默认Session中的结点展开状态恢复到指定树，在树结点添加结束后调用
    /// </summary>
    /// <param name="tree">目标树</param>
    public static void RestoreExpandStateToTreeFromSession(TreeView tree)
    {
        RestoreExpandStateToTreeFromSession(tree, SessionKey);
    }

    #region IDisposable 成员

    public void Dispose()
    {
        this.nodes.Clear();
        this.nodes = null;
        this._tree.Dispose();
    }

    #endregion

    ~TreeNodesExpandStateManager()
    {
        this.Dispose();
    }

    public class EqualEntity : IEqualityComparer<TreeNode>
    {
        #region IEqualityComparer<TreeNode> 成员

        public bool Equals(TreeNode x, TreeNode y)
        {
            if (x == null || y == null)
                return false;
            return x.Value.Equals(y.Value);
        }

        public int GetHashCode(TreeNode obj)
        {
            return obj.GetHashCode();
        }

        #endregion
    }
}